<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>视频水印添加工具</title>
    <!-- Cropper.js CSS -->
    <link href="./videoFormat/cropper.min.css" rel="stylesheet" />
    <script src="https://cdn.bootcdn.net/ajax/libs/ffmpeg/0.11.6/ffmpeg.min.js"></script>
    <script src="./ffmpeg-core.js"></script>
    <!-- Cropper.js JavaScript -->
    <script src="./videoFormat/cropper.min.js"></script>
    <style>
      * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
        font-family: 'SF Pro Display', 'PingFang SC', 'Helvetica Neue', Arial,
          sans-serif;
      }

      :root {
        --primary-bg: #e6e7ee;
        --secondary-bg: #ffffff;
        --shadow-light: #ffffff;
        --shadow-dark: #d1d9e6;
        --accent-color: #667eea;
        --accent-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        --success-color: #4ecdc4;
        --danger-color: #ff6b6b;
        --warning-color: #feca57;
        --text-primary: #2d3748;
        --text-secondary: #718096;
        --glass-bg: rgba(255, 255, 255, 0.25);
        --glass-border: rgba(255, 255, 255, 0.18);
        --border-radius: 20px;
        --shadow-large: 15px 15px 30px var(--shadow-dark),
          -15px -15px 30px var(--shadow-light);
      }

      body {
        background: var(--primary-bg);
        color: var(--text-primary);
        min-height: 100vh;
        padding: 20px;
        display: flex;
        flex-direction: column;
        align-items: center;
        transition: all 0.3s ease;
        animation: pageLoad 0.8s ease;
      }

      @keyframes pageLoad {
        from {
          opacity: 0;
          transform: translateY(20px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .container {
        width: 100%;
        max-width: 1200px;
        background: var(--primary-bg);
        border-radius: 30px;
        padding: 40px;
        box-shadow: 20px 20px 60px var(--shadow-dark),
          -20px -20px 60px var(--shadow-light);
        margin-top: 20px;
        transition: all 0.3s ease;
        animation: containerFloat 1s ease 0.2s both;
      }

      @keyframes containerFloat {
        from {
          opacity: 0;
          transform: translateY(30px) scale(0.95);
        }
        to {
          opacity: 1;
          transform: translateY(0) scale(1);
        }
      }

      .container:hover {
        box-shadow: 25px 25px 70px var(--shadow-dark),
          -25px -25px 70px var(--shadow-light);
      }

      header {
        text-align: center;
        margin-bottom: 40px;
        padding: 30px;
        background: var(--primary-bg);
        border-radius: 25px;
        box-shadow: 10px 10px 20px var(--shadow-dark),
          -10px -10px 20px var(--shadow-light);
        animation: headerSlide 0.8s ease 0.4s both;
      }

      @keyframes headerSlide {
        from {
          opacity: 0;
          transform: translateY(-30px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      h1 {
        font-size: 3.2rem;
        margin-bottom: 15px;
        background: var(--accent-gradient);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        background-clip: text;
        font-weight: 700;
        animation: titleGlow 3s ease-in-out infinite alternate;
      }

      @keyframes titleGlow {
        from {
          filter: brightness(1);
        }
        to {
          filter: brightness(1.2);
        }
      }

      .subtitle {
        font-size: 1.3rem;
        color: var(--text-secondary);
        margin-bottom: 30px;
        font-weight: 500;
      }

      .main-content {
        display: grid;
        grid-template-columns: 2fr 1fr;
        gap: 30px;
        margin-bottom: 40px;
        animation: panelsSlide 0.8s ease 0.6s both;
        align-items: start;
      }

      @media (max-width: 1024px) {
        .main-content {
          grid-template-columns: 1fr;
          gap: 25px;
        }

        .control-panel {
          order: 2;
        }

        .video-panel {
          order: 1;
        }
      }

      @media (max-width: 768px) {
        .main-content {
          gap: 20px;
        }

        .video-panel,
        .control-panel {
          padding: 20px;
        }

        .time-controls,
        .watermark-settings,
        .output-settings {
          padding: 20px;
        }

        .action-buttons {
          flex-direction: column;
          gap: 10px;
        }
      }

      @keyframes panelsSlide {
        from {
          opacity: 0;
          transform: translateX(-20px);
        }
        to {
          opacity: 1;
          transform: translateX(0);
        }
      }

      .video-panel {
        background: var(--primary-bg);
        border-radius: 25px;
        padding: 30px;
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
        transition: all 0.3s ease;
        position: relative;
        overflow: hidden;
        display: flex;
        flex-direction: column;
        gap: 25px;
      }

      .video-panel::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(
          90deg,
          transparent,
          rgba(255, 255, 255, 0.1),
          transparent
        );
        transition: left 0.8s;
      }

      .video-panel:hover::before {
        left: 100%;
      }

      .video-panel:hover {
        transform: translateY(-5px);
        box-shadow: 16px 16px 32px var(--shadow-dark),
          -16px -16px 32px var(--shadow-light);
      }

      .control-panel {
        background: var(--primary-bg);
        border-radius: 25px;
        padding: 30px;
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
        transition: all 0.3s ease;
        position: relative;
        overflow: hidden;
        display: flex;
        flex-direction: column;
        gap: 25px;
      }

      .time-controls,
      .watermark-settings,
      .output-settings {
        background: rgba(255, 255, 255, 0.02);
        border-radius: 20px;
        padding: 25px;
        border: 1px solid rgba(255, 255, 255, 0.05);
        box-shadow: inset 6px 6px 12px var(--shadow-dark),
          inset -6px -6px 12px var(--shadow-light);
        transition: all 0.3s ease;
        margin-top: 0;
      }

      .video-panel .time-controls,
      .video-panel .watermark-settings {
        background: rgba(255, 255, 255, 0.05);
        border: 1px solid rgba(255, 255, 255, 0.1);
      }

      .time-controls:hover,
      .watermark-settings:hover,
      .output-settings:hover {
        transform: translateY(-2px);
        box-shadow: inset 8px 8px 16px var(--shadow-dark),
          inset -8px -8px 16px var(--shadow-light),
          0 8px 20px rgba(0, 0, 0, 0.1);
      }

      .action-buttons {
        display: flex;
        gap: 15px;
        justify-content: center;
        flex-wrap: wrap;
        margin-top: 10px;
      }

      .control-panel::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(
          90deg,
          transparent,
          rgba(255, 255, 255, 0.1),
          transparent
        );
        transition: left 0.8s;
      }

      .control-panel:hover::before {
        left: 100%;
      }

      .control-panel:hover {
        transform: translateY(-5px);
        box-shadow: 16px 16px 32px var(--shadow-dark),
          -16px -16px 32px var(--shadow-light);
      }

      .panel-title {
        font-size: 1.6rem;
        margin-bottom: 25px;
        color: var(--accent-color);
        display: flex;
        align-items: center;
        font-weight: 600;
      }

      .panel-title::before {
        content: attr(data-icon);
        margin-right: 12px;
        font-size: 1.8rem;
        animation: iconBounce 2s ease-in-out infinite;
      }

      @keyframes iconBounce {
        0%,
        100% {
          transform: scale(1);
        }
        50% {
          transform: scale(1.1);
        }
      }

      .file-upload {
        border: 3px dashed var(--accent-color);
        border-radius: 25px;
        padding: 50px 40px;
        text-align: center;
        transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
        margin-bottom: 25px;
        cursor: pointer;
        background: var(--primary-bg);
        box-shadow: inset 8px 8px 16px var(--shadow-dark),
          inset -8px -8px 16px var(--shadow-light);
        position: relative;
        overflow: hidden;
      }

      .file-upload:hover {
        border-color: var(--success-color);
        transform: translateY(-5px) scale(1.02);
        box-shadow: inset 10px 10px 20px var(--shadow-dark),
          inset -10px -10px 20px var(--shadow-light),
          0 15px 40px rgba(102, 126, 234, 0.25), 0 5px 15px rgba(0, 0, 0, 0.1);
      }

      .file-upload.dragover {
        border-color: var(--success-color);
        background: rgba(78, 205, 196, 0.05);
        transform: scale(1.05);
        box-shadow: inset 12px 12px 24px var(--shadow-dark),
          inset -12px -12px 24px var(--shadow-light),
          0 20px 50px rgba(78, 205, 196, 0.3);
        animation: dragPulse 1s ease-in-out infinite;
      }

      @keyframes dragPulse {
        0%,
        100% {
          border-color: var(--success-color);
        }
        50% {
          border-color: var(--accent-color);
        }
      }

      .file-upload-content {
        position: relative;
        z-index: 1;
      }

      .file-upload-icon {
        font-size: 3.5rem;
        margin-bottom: 20px;
        display: block;
        animation: iconFloat 3s ease-in-out infinite;
        filter: drop-shadow(0 4px 8px rgba(102, 126, 234, 0.2));
      }

      @keyframes iconFloat {
        0%,
        100% {
          transform: translateY(0);
        }
        50% {
          transform: translateY(-10px);
        }
      }

      .file-upload-text {
        font-size: 1.4rem;
        font-weight: 600;
        color: var(--text-primary);
        margin-bottom: 10px;
        background: var(--accent-gradient);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        background-clip: text;
      }

      .file-upload-subtext {
        font-size: 1.1rem;
        color: var(--text-secondary);
        margin-bottom: 20px;
        font-weight: 500;
      }

      .file-upload-formats {
        font-size: 0.9rem;
        color: var(--accent-color);
        font-weight: 500;
        padding: 8px 16px;
        background: rgba(102, 126, 234, 0.1);
        border-radius: 20px;
        display: inline-block;
        margin-bottom: 20px;
      }

      .file-upload input[type='file'] {
        position: absolute;
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        opacity: 0;
        cursor: pointer;
        z-index: 2;
      }

      .video-container {
        position: relative;
        width: 100%;
        background: var(--primary-bg);
        border-radius: 20px;
        overflow: hidden;
        margin-top: 20px;
        box-shadow: inset 10px 10px 20px var(--shadow-dark),
          inset -10px -10px 20px var(--shadow-light);
        transition: all 0.3s ease;
      }

      .video-container:hover {
        box-shadow: inset 12px 12px 24px var(--shadow-dark),
          inset -12px -12px 24px var(--shadow-light);
      }

      video {
        width: 100%;
        height: auto;
        display: block;
        border-radius: 15px;
      }

      .watermark-region {
        position: absolute;
        border: 3px solid var(--accent-color);
        background: rgba(102, 126, 234, 0.15);
        cursor: move;
        pointer-events: all;
        min-width: 50px;
        min-height: 50px;
        box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.3),
          0 0 20px rgba(102, 126, 234, 0.4);
        transition: all 0.3s ease;
        touch-action: none;
        border-radius: 8px;
        user-select: none;
        display: flex;
        align-items: center;
        justify-content: center;
        color: white;
        font-weight: bold;
        text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8);
        font-size: 14px;
        text-align: center;
        overflow: hidden;
      }

      .watermark-region:hover {
        border-color: var(--warning-color);
        background: rgba(254, 202, 87, 0.15);
        box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.4),
          0 0 30px rgba(254, 202, 87, 0.5);
      }

      .watermark-region.selected {
        border-color: var(--success-color);
        background: rgba(78, 205, 196, 0.15);
        box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.4),
          0 0 30px rgba(78, 205, 196, 0.5);
      }

      .watermark-region img {
        max-width: 100%;
        max-height: 100%;
        object-fit: contain;
      }

      .region-handle {
        position: absolute;
        width: 16px;
        height: 16px;
        background: var(--accent-color);
        border: 3px solid white;
        border-radius: 50%;
        cursor: pointer;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
        transition: all 0.3s ease;
        z-index: 20;
        touch-action: none;
      }

      .region-handle:hover {
        transform: scale(1.2);
        box-shadow: 0 4px 16px rgba(102, 126, 234, 0.4);
      }

      .region-handle.nw {
        top: -8px;
        left: -8px;
        cursor: nw-resize;
      }
      .region-handle.ne {
        top: -8px;
        right: -8px;
        cursor: ne-resize;
      }
      .region-handle.sw {
        bottom: -8px;
        left: -8px;
        cursor: sw-resize;
      }
      .region-handle.se {
        bottom: -8px;
        right: -8px;
        cursor: se-resize;
      }
      .region-handle.n {
        top: -8px;
        left: 50%;
        transform: translateX(-50%);
        cursor: n-resize;
      }
      .region-handle.s {
        bottom: -8px;
        left: 50%;
        transform: translateX(-50%);
        cursor: s-resize;
      }
      .region-handle.w {
        top: 50%;
        left: -8px;
        transform: translateY(-50%);
        cursor: w-resize;
      }
      .region-handle.e {
        top: 50%;
        right: -8px;
        transform: translateY(-50%);
        cursor: e-resize;
      }

      .region-label {
        position: absolute;
        top: -30px;
        left: 0;
        background: var(--accent-color);
        color: white;
        padding: 4px 8px;
        border-radius: 12px;
        font-size: 0.8rem;
        font-weight: 600;
        white-space: nowrap;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
      }

      .region-delete {
        position: absolute;
        top: -12px;
        right: -12px;
        width: 24px;
        height: 24px;
        background: var(--danger-color);
        color: white;
        border: none;
        border-radius: 50%;
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 0.8rem;
        font-weight: bold;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
        transition: all 0.3s ease;
        z-index: 21;
      }

      .region-delete:hover {
        transform: scale(1.1);
        box-shadow: 0 4px 16px rgba(255, 107, 107, 0.4);
      }

      .form-group {
        margin-bottom: 25px;
      }

      label {
        display: block;
        margin-bottom: 10px;
        color: var(--text-secondary);
        font-weight: 500;
        font-size: 0.95rem;
      }

      input,
      select,
      textarea {
        width: 100%;
        padding: 14px 18px;
        background: var(--primary-bg);
        border: none;
        border-radius: 15px;
        color: var(--text-primary);
        font-size: 1rem;
        font-weight: 500;
        box-shadow: inset 6px 6px 12px var(--shadow-dark),
          inset -6px -6px 12px var(--shadow-light);
        transition: all 0.3s ease;
      }

      input:focus,
      select:focus,
      textarea:focus {
        outline: none;
        box-shadow: inset 8px 8px 16px var(--shadow-dark),
          inset -8px -8px 16px var(--shadow-light),
          0 0 0 3px rgba(102, 126, 234, 0.2);
      }

      textarea {
        resize: vertical;
        min-height: 80px;
      }

      button {
        background: var(--primary-bg);
        color: var(--text-primary);
        border: none;
        padding: 14px 28px;
        border-radius: 15px;
        cursor: pointer;
        font-weight: 600;
        transition: all 0.3s ease;
        font-size: 1rem;
        flex-shrink: 0;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light);
        position: relative;
        overflow: hidden;
        min-width: 140px;
      }

      .form-group button,
      .watermark-settings button {
        width: 100%;
        margin-bottom: 15px;
      }

      .action-buttons button {
        flex: 1;
        min-width: 180px;
        margin-bottom: 0;
      }

      button::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(
          90deg,
          transparent,
          rgba(255, 255, 255, 0.2),
          transparent
        );
        transition: left 0.5s;
      }

      button:hover::before {
        left: 100%;
      }

      button:hover {
        transform: translateY(-3px);
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
      }

      button:active {
        transform: translateY(0);
        box-shadow: inset 6px 6px 12px var(--shadow-dark),
          inset -6px -6px 12px var(--shadow-light);
      }

      button:disabled {
        opacity: 0.6;
        cursor: not-allowed;
        transform: none;
        box-shadow: 4px 4px 8px var(--shadow-dark),
          -4px -4px 8px var(--shadow-light);
      }

      .btn-primary {
        background: var(--accent-gradient);
        color: white;
        padding: 16px 32px;
        font-size: 1.1rem;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2);
      }

      .btn-primary:hover {
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2),
          0 0 30px rgba(102, 126, 234, 0.3);
      }

      .btn-success {
        background: linear-gradient(
          135deg,
          var(--success-color) 0%,
          #44a08d 100%
        );
        color: white;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2);
      }

      .btn-warning {
        background: linear-gradient(
          135deg,
          var(--warning-color) 0%,
          #f39c12 100%
        );
        color: white;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2);
      }

      .btn-danger {
        background: linear-gradient(
          135deg,
          var(--danger-color) 0%,
          #c0392b 100%
        );
        color: white;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2);
      }

      .time-controls {
        background: var(--primary-bg);
        border-radius: var(--border-radius);
        padding: 20px;
        margin-bottom: 20px;
        box-shadow: inset 5px 5px 10px var(--shadow-dark),
          inset -5px -5px 10px var(--shadow-light);
      }

      .time-input-group {
        display: flex;
        gap: 15px;
        align-items: center;
        margin-bottom: 15px;
      }

      .time-input {
        flex: 1;
        padding: 10px 15px;
        border: none;
        border-radius: 10px;
        background: var(--secondary-bg);
        box-shadow: inset 3px 3px 6px var(--shadow-dark),
          inset -3px -3px 6px var(--shadow-light);
        transition: all 0.3s ease;
      }

      .time-slider {
        width: 100%;
        height: 8px;
        border-radius: 5px;
        background: var(--primary-bg);
        outline: none;
        box-shadow: inset 3px 3px 6px var(--shadow-dark),
          inset -3px -3px 6px var(--shadow-light);
        -webkit-appearance: none;
        appearance: none;
      }

      .time-slider::-webkit-slider-thumb {
        appearance: none;
        width: 20px;
        height: 20px;
        border-radius: 50%;
        background: var(--accent-gradient);
        cursor: pointer;
        box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
        transition: all 0.3s ease;
      }

      .time-slider::-webkit-slider-thumb:hover {
        transform: scale(1.2);
        box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
      }

      .progress-container {
        margin-top: 30px;
        padding: 25px;
        background: var(--primary-bg);
        border-radius: 20px;
        box-shadow: inset 8px 8px 16px var(--shadow-dark),
          inset -8px -8px 16px var(--shadow-light);
        animation: progressSlide 0.5s ease;
      }

      @keyframes progressSlide {
        from {
          opacity: 0;
          transform: translateY(20px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .progress-bar {
        width: 100%;
        height: 12px;
        background: var(--primary-bg);
        border-radius: 6px;
        overflow: hidden;
        box-shadow: inset 4px 4px 8px var(--shadow-dark),
          inset -4px -4px 8px var(--shadow-light);
        margin-bottom: 15px;
      }

      .progress-fill {
        height: 100%;
        background: var(--accent-gradient);
        border-radius: 6px;
        transition: width 0.3s ease;
        box-shadow: 0 0 10px rgba(102, 126, 234, 0.3);
      }

      .progress-text {
        text-align: center;
        color: var(--text-primary);
        font-weight: 600;
        font-size: 1.1rem;
      }

      .status-message {
        padding: 15px 20px;
        margin: 20px 0;
        border-radius: 15px;
        background: rgba(78, 205, 196, 0.1);
        border-left: 4px solid var(--success-color);
        color: var(--success-color);
        font-weight: 600;
        animation: statusSlide 0.3s ease;
      }

      .error-message {
        padding: 15px 20px;
        margin: 20px 0;
        border-radius: 15px;
        background: rgba(255, 107, 107, 0.1);
        border-left: 4px solid var(--danger-color);
        color: var(--danger-color);
        font-weight: 600;
        animation: errorShake 0.5s ease;
      }

      @keyframes statusSlide {
        from {
          opacity: 0;
          transform: translateX(-20px);
        }
        to {
          opacity: 1;
          transform: translateX(0);
        }
      }

      @keyframes errorShake {
        0%,
        100% {
          transform: translateX(0);
        }
        25% {
          transform: translateX(-5px);
        }
        75% {
          transform: translateX(5px);
        }
      }

      /* 模态弹窗样式 */
      .modal {
        position: fixed;
        z-index: 1000;
        left: 0;
        top: 0;
        width: 100vw;
        height: 100vh;
        background-color: rgba(0, 0, 0, 0.5);
        backdrop-filter: blur(5px);
        display: flex;
        justify-content: center;
        align-items: center;
        animation: modalFadeIn 0.3s ease;
      }

      @keyframes modalFadeIn {
        from {
          opacity: 0;
        }
        to {
          opacity: 1;
        }
      }

      .modal-content {
        background: var(--primary-bg);
        border-radius: 25px;
        box-shadow: 20px 20px 60px var(--shadow-dark),
          -20px -20px 60px var(--shadow-light);
        width: 90%;
        max-width: 1000px;
        max-height: 90vh;
        overflow: hidden;
        animation: modalSlideIn 0.3s ease;
        display: flex;
        flex-direction: column;
      }

      @keyframes modalSlideIn {
        from {
          transform: translateY(-50px) scale(0.9);
          opacity: 0;
        }
        to {
          transform: translateY(0) scale(1);
          opacity: 1;
        }
      }

      .modal-header {
        padding: 25px 30px;
        border-bottom: 1px solid var(--shadow-dark);
        display: flex;
        justify-content: space-between;
        align-items: center;
        background: var(--primary-bg);
      }

      .modal-header h3 {
        margin: 0;
        color: var(--accent-color);
        font-size: 1.5rem;
        font-weight: 600;
      }

      .modal-close {
        font-size: 2rem;
        color: var(--text-secondary);
        cursor: pointer;
        transition: all 0.3s ease;
        width: 40px;
        height: 40px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 50%;
        background: var(--primary-bg);
        box-shadow: 5px 5px 10px var(--shadow-dark),
          -5px -5px 10px var(--shadow-light);
      }

      .modal-close:hover {
        color: var(--danger-color);
        transform: scale(1.1);
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light);
      }

      .modal-body {
        padding: 30px;
        flex: 1;
        overflow-y: auto;
        min-height: 0;
      }

      .video-info {
        display: flex;
        justify-content: space-between;
        margin-bottom: 20px;
        padding: 15px;
        background: var(--primary-bg);
        border-radius: 15px;
        box-shadow: inset 5px 5px 10px var(--shadow-dark),
          inset -5px -5px 10px var(--shadow-light);
      }

      .video-info span {
        font-weight: 500;
        color: var(--text-primary);
      }

      .cropper-container {
        margin-top: 20px;
        border-radius: 15px;
        overflow: hidden;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light);
      }

      .modal-footer {
        padding: 20px 30px;
        border-top: 1px solid var(--shadow-dark);
        display: flex;
        gap: 15px;
        justify-content: center;
        background: var(--primary-bg);
        flex-shrink: 0;
      }

      .modal-footer button {
        width: auto;
        margin: 0;
        padding: 12px 30px;
      }

      .watermark-list {
        max-height: 300px;
        overflow-y: auto;
      }

      .watermark-item {
        background: var(--primary-bg);
        border-radius: 15px;
        padding: 15px;
        margin-bottom: 10px;
        box-shadow: 6px 6px 12px var(--shadow-dark),
          -6px -6px 12px var(--shadow-light);
        transition: all 0.3s ease;
      }

      .watermark-item:hover {
        transform: translateY(-2px);
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light);
      }

      .watermark-item-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 10px;
      }

      .watermark-item-title {
        font-weight: 600;
        color: var(--text-primary);
      }

      .watermark-item-info {
        font-size: 0.9rem;
        color: var(--text-secondary);
        margin-bottom: 10px;
      }

      .watermark-item-actions {
        display: flex;
        gap: 10px;
      }

      .watermark-item-actions button {
        flex: 1;
        margin: 0;
        padding: 8px 16px;
        font-size: 0.9rem;
        min-width: auto;
      }

      .operation-history {
        background: var(--primary-bg);
        border-radius: 25px;
        padding: 30px;
        margin-top: 40px;
        box-shadow: 10px 10px 20px var(--shadow-dark),
          -10px -10px 20px var(--shadow-light);
        animation: historySlide 0.8s ease 1.2s both;
      }

      @keyframes historySlide {
        from {
          opacity: 0;
          transform: translateY(30px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .history-list {
        display: grid;
        gap: 20px;
      }

      .history-item {
        background: rgba(255, 255, 255, 0.05);
        border-radius: 20px;
        padding: 25px;
        box-shadow: inset 5px 5px 10px var(--shadow-dark),
          inset -5px -5px 10px var(--shadow-light);
        transition: all 0.3s ease;
        border: 1px solid rgba(102, 126, 234, 0.2);
      }

      .history-item:hover {
        transform: translateY(-2px);
        box-shadow: 5px 5px 15px var(--shadow-dark),
          -5px -5px 15px var(--shadow-light);
      }

      .history-item-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 15px;
      }

      .history-item-title {
        font-size: 1.1rem;
        font-weight: 600;
        color: var(--text-primary);
      }

      .history-item-time {
        font-size: 0.9rem;
        color: var(--text-secondary);
        opacity: 0.8;
      }

      .history-item-info {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
        gap: 15px;
        margin-bottom: 20px;
        font-size: 0.9rem;
        color: var(--text-secondary);
      }

      .history-item-actions {
        display: flex;
        gap: 15px;
        flex-wrap: wrap;
      }

      .history-item-actions button {
        flex: 1;
        min-width: 120px;
        margin: 0;
        padding: 12px 20px;
        font-size: 0.9rem;
        font-weight: 500;
        border-radius: 15px;
        transition: all 0.3s ease;
      }

      .btn-preview {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        color: white;
        border: none;
      }

      .btn-preview:hover {
        transform: translateY(-2px);
        box-shadow: 0 8px 20px rgba(102, 126, 234, 0.4);
      }

      .btn-download {
        background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
        color: white;
        border: none;
      }

      .btn-download:hover {
        transform: translateY(-2px);
        box-shadow: 0 8px 20px rgba(17, 153, 142, 0.4);
      }

      .btn-delete {
        background: linear-gradient(135deg, #ff6b6b 0%, #ee5a24 100%);
        color: white;
        border: none;
      }

      .btn-delete:hover {
        transform: translateY(-2px);
        box-shadow: 0 8px 20px rgba(255, 107, 107, 0.4);
      }

      .instructions {
        background: var(--primary-bg);
        border-radius: 25px;
        padding: 30px;
        margin-top: 40px;
        box-shadow: 10px 10px 20px var(--shadow-dark),
          -10px -10px 20px var(--shadow-light);
        animation: instructionsSlide 0.8s ease 1.4s both;
      }

      @keyframes instructionsSlide {
        from {
          opacity: 0;
          transform: translateY(30px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .instructions h3 {
        color: var(--accent-color);
        margin-bottom: 20px;
        font-size: 1.4rem;
        font-weight: 600;
      }

      .instructions ol {
        padding-left: 25px;
        margin-bottom: 20px;
      }

      .instructions li {
        margin-bottom: 12px;
        line-height: 1.7;
        color: var(--text-secondary);
        font-weight: 500;
      }

      .instructions p {
        color: var(--text-secondary);
        font-style: italic;
        font-weight: 500;
        padding: 15px;
        background: rgba(102, 126, 234, 0.1);
        border-radius: 15px;
        border-left: 4px solid var(--accent-color);
      }

      @media (max-width: 1200px) {
        .main-content {
          grid-template-columns: 1fr;
          gap: 20px;
        }

        .control-panel {
          order: -1;
        }
      }

      @media (max-width: 768px) {
        .container {
          padding: 20px;
          margin: 10px;
        }

        h1 {
          font-size: 2.5rem;
        }

        .subtitle {
          font-size: 1.1rem;
        }

        .time-input-group {
          flex-direction: column;
          gap: 10px;
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <header>
        <h1>🎬 视频水印添加工具</h1>
        <p class="subtitle">为视频添加自定义水印，支持文字和图片水印</p>
      </header>

      <div class="main-content">
        <!-- 视频预览区域 -->
        <div class="video-panel">
          <div class="panel-title" data-icon="🎥">视频预览</div>

          <div class="file-upload" id="fileUpload">
            <div class="file-upload-content">
              <span class="file-upload-icon">📁</span>
              <div class="file-upload-text">点击或拖拽上传视频文件</div>
              <div class="file-upload-subtext">支持多种视频格式</div>
              <div class="file-upload-formats">MP4, AVI, MOV, MKV, WebM</div>
            </div>
          </div>
          <input
            type="file"
            id="videoInput"
            accept="video/*"
            style="display: none"
          />

          <div
            class="video-container"
            id="videoContainer"
            style="display: none"
          >
            <video id="videoPreview" controls></video>
          </div>

          <!-- 时间控制区域 -->
          <div class="time-controls" id="videoControls" style="display: none">
            <div class="panel-title" data-icon="⏱️">时间范围设置</div>
            <div class="time-input-group">
              <div>
                <label>开始时间 (秒)</label>
                <input
                  type="number"
                  id="startTime"
                  class="time-input"
                  value="0"
                  min="0"
                  step="0.1"
                />
              </div>
              <div>
                <label>结束时间 (秒)</label>
                <input
                  type="number"
                  id="endTime"
                  class="time-input"
                  value="10"
                  min="0"
                  step="0.1"
                />
              </div>
            </div>
            <input
              type="range"
              id="timeSlider"
              class="time-slider"
              min="0"
              max="100"
              value="0"
              step="0.1"
              style="padding-left: 0"
            />
            <div
              style="
                display: flex;
                gap: 10px;
                justify-content: center;
                margin-top: 10px;
              "
            >
              <button
                class="btn-small"
                onclick="watermarkAdder.setCurrentTimeAsStart()"
              >
                设为开始时间
              </button>
              <button
                class="btn-small"
                onclick="watermarkAdder.setCurrentTimeAsEnd()"
              >
                设为结束时间
              </button>
            </div>
          </div>

          <!-- 水印设置区域 -->
          <div class="watermark-settings">
            <div class="panel-title" data-icon="⚙️">水印设置</div>

            <div class="form-group">
              <button id="addWatermarkBtn" class="btn-primary">
                ➕ 添加水印区域
              </button>
            </div>

            <div class="watermark-list" id="watermarkList">
              <div
                style="
                  text-align: center;
                  color: var(--text-secondary);
                  padding: 20px;
                "
              >
                暂无水印区域<br />
                <small>点击上方按钮添加水印区域</small>
              </div>
            </div>
          </div>
        </div>

        <!-- 控制面板区域 -->
        <div class="control-panel">
          <!-- 输出设置区域 -->
          <div class="output-settings">
            <div class="panel-title" data-icon="🎬">输出设置</div>

            <div class="form-group">
              <label for="outputFormat">输出格式</label>
              <select id="outputFormat">
                <option value="mp4">MP4 (推荐)</option>
                <option value="avi">AVI</option>
                <option value="mov">MOV</option>
                <option value="mkv">MKV</option>
              </select>
            </div>

            <div class="form-group">
              <label for="quality">视频质量</label>
              <select id="quality">
                <option value="high">高质量 (较慢)</option>
                <option value="medium" selected>中等质量 (推荐)</option>
                <option value="low">低质量 (较快)</option>
              </select>
            </div>
          </div>

          <!-- 操作按钮区域 -->
          <div class="action-buttons">
            <button id="processBtn" class="btn-success" disabled>
              🚀 开始添加水印
            </button>
            <button id="clearAllBtn" class="btn-danger">🗑️ 清除所有区域</button>
          </div>
        </div>
      </div>

      <div
        class="progress-container"
        id="progressContainer"
        style="display: none"
      >
        <div class="progress-bar">
          <div class="progress-fill" id="progressFill"></div>
        </div>
        <div class="progress-text" id="progressText">准备处理...</div>
      </div>

      <!-- 状态消息 -->
      <div
        id="statusMessage"
        class="status-message"
        style="display: none"
      ></div>
      <div id="errorMessage" class="error-message" style="display: none"></div>

      <!-- 操作记录列表 -->
      <div
        class="operation-history"
        id="operationHistory"
        style="display: none"
      >
        <h3
          style="
            color: var(--accent-color);
            margin-bottom: 20px;
            text-align: center;
          "
        >
          📋 处理记录
        </h3>
        <div class="history-list" id="historyList"></div>
      </div>

      <!-- 使用说明 -->
      <div class="instructions">
        <h3>📖 使用说明</h3>
        <ol>
          <li>上传需要添加水印的视频文件</li>
          <li>设置水印显示的时间范围（开始时间和结束时间）</li>
          <li>点击"添加水印区域"按钮，在弹出的窗口中选择水印位置</li>
          <li>选择水印类型（文字或图片）并设置相关参数</li>
          <li>可以添加多个水印区域，每个区域可以有不同的内容和样式</li>
          <li>选择输出格式和质量，点击"开始添加水印"进行处理</li>
        </ol>
        <p>
          💡
          提示：支持文字水印和图片水印，可以调整透明度、颜色、大小等属性。处理完成后可以预览和下载结果。
        </p>
      </div>
    </div>
    <!-- 水印区域选择模态弹窗 -->
    <div class="modal" id="watermarkModal" style="display: none">
      <div class="modal-content">
        <div class="modal-header">
          <h3>🎯 选择水印位置</h3>
          <span class="modal-close" id="modalClose">&times;</span>
        </div>
        <div class="modal-body">
          <div class="video-info">
            <span id="videoResolution">视频尺寸: 加载中...</span>
            <span id="selectionInfo">选择区域: 未选择</span>
          </div>
          <div class="cropper-container">
            <img id="cropperImage" style="max-width: 100%" />
          </div>

          <!-- 水印内容设置 -->
          <div style="margin-top: 20px">
            <div class="form-group">
              <label>水印类型</label>
              <select id="watermarkType">
                <option value="text">文字水印</option>
                <option value="image">图片水印</option>
              </select>
            </div>

            <!-- 文字水印设置 -->
            <div id="textWatermarkSettings">
              <div class="form-group">
                <label>水印文字</label>
                <input
                  type="text"
                  id="watermarkText"
                  placeholder="请输入水印文字"
                  value="水印文字"
                />
              </div>
              <div class="form-group">
                <label>字体大小</label>
                <input
                  type="number"
                  id="fontSize"
                  value="24"
                  min="12"
                  max="100"
                />
              </div>
              <div class="form-group">
                <label>字体颜色</label>
                <input type="color" id="fontColor" value="#ffffff" />
              </div>
              <div class="form-group">
                <label>透明度</label>
                <input
                  type="range"
                  id="opacity"
                  min="0"
                  max="1"
                  step="0.1"
                  value="0.8"
                />
                <span id="opacityValue">0.8</span>
              </div>
            </div>

            <!-- 图片水印设置 -->
            <div id="imageWatermarkSettings" style="display: none">
              <div class="form-group">
                <label>选择水印图片</label>
                <input type="file" id="watermarkImage" accept="image/*" />
              </div>
              <div class="form-group">
                <label>图片透明度</label>
                <input
                  type="range"
                  id="imageOpacity"
                  min="0"
                  max="1"
                  step="0.1"
                  value="0.8"
                />
                <span id="imageOpacityValue">0.8</span>
              </div>
            </div>
          </div>
        </div>
        <div class="modal-footer">
          <button id="confirmCropBtn" class="btn-success">✅ 确认添加</button>
          <button id="cancelCropBtn" class="btn-danger">❌ 取消</button>
        </div>
      </div>
    </div>

    <script>
      class WatermarkAdder {
        constructor() {
          this.ffmpeg = null
          this.videoFile = null
          this.watermarkRegions = []
          this.regionCounter = 0
          this.cropper = null
          this.canvas = null
          this.watermarkImageFile = null
          this.processHistory = []

          this.initializeElements()
          this.setupEventListeners()
          this.loadFFmpeg()
        }

        initializeElements() {
          // 基础元素
          this.fileUpload = document.getElementById('fileUpload')
          this.videoInput = document.getElementById('videoInput')
          this.videoPreview = document.getElementById('videoPreview')
          this.videoContainer = document.getElementById('videoContainer')
          this.addWatermarkBtn = document.getElementById('addWatermarkBtn')
          this.watermarkList = document.getElementById('watermarkList')
          this.processBtn = document.getElementById('processBtn')
          this.clearAllBtn = document.getElementById('clearAllBtn')
          this.progressContainer = document.getElementById('progressContainer')
          this.progressFill = document.getElementById('progressFill')
          this.progressText = document.getElementById('progressText')
          this.statusMessage = document.getElementById('statusMessage')
          this.errorMessage = document.getElementById('errorMessage')
          this.outputFormat = document.getElementById('outputFormat')
          this.quality = document.getElementById('quality')

          // Cropper相关元素
          this.cropperImage = document.getElementById('cropperImage')
          this.confirmCropBtn = document.getElementById('confirmCropBtn')
          this.cancelCropBtn = document.getElementById('cancelCropBtn')

          // 水印设置元素
          this.watermarkType = document.getElementById('watermarkType')
          this.watermarkText = document.getElementById('watermarkText')
          this.fontSize = document.getElementById('fontSize')
          this.fontColor = document.getElementById('fontColor')
          this.opacity = document.getElementById('opacity')
          this.opacityValue = document.getElementById('opacityValue')
          this.watermarkImage = document.getElementById('watermarkImage')
          this.imageOpacity = document.getElementById('imageOpacity')
          this.imageOpacityValue = document.getElementById('imageOpacityValue')
          this.textWatermarkSettings = document.getElementById(
            'textWatermarkSettings'
          )
          this.imageWatermarkSettings = document.getElementById(
            'imageWatermarkSettings'
          )

          // 历史记录相关元素
          this.operationHistory = document.getElementById('operationHistory')
          this.historyList = document.getElementById('historyList')
        }

        setupEventListeners() {
          // 文件上传
          this.fileUpload.addEventListener('click', () =>
            this.videoInput.click()
          )
          this.videoInput.addEventListener('change', (e) =>
            this.handleFileSelect(e)
          )

          // 拖拽上传
          this.fileUpload.addEventListener('dragover', (e) => {
            e.preventDefault()
            this.fileUpload.classList.add('dragover')
          })

          this.fileUpload.addEventListener('dragleave', () => {
            this.fileUpload.classList.remove('dragover')
          })

          this.fileUpload.addEventListener('drop', (e) => {
            e.preventDefault()
            this.fileUpload.classList.remove('dragover')
            const files = e.dataTransfer.files
            if (files.length > 0) {
              this.handleFile(files[0])
            }
          })

          // 按钮事件
          this.addWatermarkBtn.addEventListener('click', () =>
            this.showCropper()
          )
          this.processBtn.addEventListener('click', () => this.processVideo())
          this.clearAllBtn.addEventListener('click', () =>
            this.clearAllRegions()
          )

          // Cropper按钮事件
          this.confirmCropBtn.addEventListener('click', () =>
            this.confirmCrop()
          )
          this.cancelCropBtn.addEventListener('click', () => this.cancelCrop())

          // 水印类型切换
          this.watermarkType.addEventListener('change', () => {
            this.toggleWatermarkSettings()
          })

          // 透明度滑块
          this.opacity.addEventListener('input', (e) => {
            this.opacityValue.textContent = e.target.value
          })

          this.imageOpacity.addEventListener('input', (e) => {
            this.imageOpacityValue.textContent = e.target.value
          })

          // 水印图片选择
          this.watermarkImage.addEventListener('change', (e) => {
            const file = e.target.files[0]
            if (file) {
              this.watermarkImageFile = file
            }
          })

          // 模态弹窗事件
          const modal = document.getElementById('watermarkModal')
          const modalClose = document.getElementById('modalClose')

          // 关闭按钮
          modalClose.addEventListener('click', () => this.cancelCrop())

          // 点击背景关闭
          modal.addEventListener('click', (e) => {
            if (e.target === modal) {
              this.cancelCrop()
            }
          })

          // ESC键关闭
          document.addEventListener('keydown', (e) => {
            if (e.key === 'Escape' && modal.style.display === 'flex') {
              this.cancelCrop()
            }
          })

          // 视频加载完成
          this.videoPreview.addEventListener('loadedmetadata', () => {
            this.initializeTimeControls()
          })

          // 时间控制
          const timeSlider = document.getElementById('timeSlider')
          const startTime = document.getElementById('startTime')
          const endTime = document.getElementById('endTime')

          if (timeSlider) {
            timeSlider.addEventListener('input', (e) => {
              if (this.videoPreview) {
                this.videoPreview.currentTime = parseFloat(e.target.value)
              }
            })
          }

          if (startTime) {
            startTime.addEventListener('change', () => this.validateTimeRange())
          }

          if (endTime) {
            endTime.addEventListener('change', () => this.validateTimeRange())
          }
        }

        async loadFFmpeg() {
          try {
            this.showStatus('正在加载 FFmpeg...')
            this.ffmpeg = FFmpeg.createFFmpeg({
              log: true,
            })
            await this.ffmpeg.load()
            this.showStatus('FFmpeg 加载完成')
          } catch (error) {
            console.error('FFmpeg 加载失败:', error)
            this.showError('FFmpeg 加载失败，请刷新页面重试')
          }
        }

        handleFileSelect(event) {
          const file = event.target.files[0]
          if (file) {
            this.handleFile(file)
          }
        }

        handleFile(file) {
          if (!file.type.startsWith('video/')) {
            this.showError('请选择有效的视频文件')
            return
          }

          this.videoFile = file
          const url = URL.createObjectURL(file)
          this.videoPreview.src = url
          this.videoContainer.style.display = 'block'
          this.showStatus(`已加载视频: ${file.name}`)
        }

        initializeTimeControls() {
          const duration = this.videoPreview.duration
          const timeSlider = document.getElementById('timeSlider')
          const endTime = document.getElementById('endTime')

          if (timeSlider) {
            timeSlider.max = duration
          }

          if (endTime) {
            endTime.value = duration.toFixed(1)
            endTime.max = duration
          }

          document.getElementById('videoControls').style.display = 'block'
          this.updateProcessButton()
        }

        setCurrentTimeAsStart() {
          const startTime = document.getElementById('startTime')
          if (startTime && this.videoPreview) {
            startTime.value = this.videoPreview.currentTime.toFixed(1)
            this.validateTimeRange()
          }
        }

        setCurrentTimeAsEnd() {
          const endTime = document.getElementById('endTime')
          if (endTime && this.videoPreview) {
            endTime.value = this.videoPreview.currentTime.toFixed(1)
            this.validateTimeRange()
          }
        }

        validateTimeRange() {
          const startTime = parseFloat(
            document.getElementById('startTime').value
          )
          const endTime = parseFloat(document.getElementById('endTime').value)
          const duration = this.videoPreview.duration

          if (startTime >= endTime) {
            this.showError('开始时间必须小于结束时间')
            return false
          }

          if (endTime > duration) {
            this.showError('结束时间不能超过视频总时长')
            return false
          }

          this.hideError()
          return true
        }

        async showCropper() {
          if (!this.videoFile) {
            this.showError('请先上传视频文件')
            return
          }

          try {
            // 捕获当前视频帧
            const frameDataUrl = await this.captureVideoFrame()
            this.cropperImage.src = frameDataUrl

            // 显示模态弹窗
            const modal = document.getElementById('watermarkModal')
            modal.style.display = 'flex'

            // 更新视频信息
            document.getElementById(
              'videoResolution'
            ).textContent = `视频尺寸: ${this.videoPreview.videoWidth} x ${this.videoPreview.videoHeight}`

            // 初始化 Cropper
            setTimeout(() => {
              this.initializeCropper()
            }, 100)
          } catch (error) {
            console.error('显示裁剪器失败:', error)
            this.showError('无法打开水印选择器')
          }
        }

        async captureVideoFrame() {
          return new Promise((resolve) => {
            if (!this.canvas) {
              this.canvas = document.createElement('canvas')
            }

            const video = this.videoPreview
            this.canvas.width = video.videoWidth
            this.canvas.height = video.videoHeight

            const ctx = this.canvas.getContext('2d')
            ctx.drawImage(video, 0, 0, this.canvas.width, this.canvas.height)

            resolve(this.canvas.toDataURL('image/jpeg', 0.8))
          })
        }

        initializeCropper() {
          if (this.cropper) {
            this.cropper.destroy()
          }

          this.cropper = new Cropper(this.cropperImage, {
            aspectRatio: NaN,
            viewMode: 1,
            dragMode: 'crop',
            autoCropArea: 0.3,
            restore: false,
            guides: true,
            center: true,
            highlight: true,
            cropBoxMovable: true,
            cropBoxResizable: true,
            toggleDragModeOnDblclick: false,
            zoomOnWheel: false, // 禁用滚轮缩放
            crop: (event) => {
              const { x, y, width, height } = event.detail
              document.getElementById(
                'selectionInfo'
              ).textContent = `选择区域: ${Math.round(width)} x ${Math.round(
                height
              )} (${Math.round(x)}, ${Math.round(y)})`
            },
          })
        }

        toggleWatermarkSettings() {
          const type = this.watermarkType.value
          if (type === 'text') {
            this.textWatermarkSettings.style.display = 'block'
            this.imageWatermarkSettings.style.display = 'none'
          } else {
            this.textWatermarkSettings.style.display = 'none'
            this.imageWatermarkSettings.style.display = 'block'
          }
        }

        confirmCrop() {
          if (!this.cropper) {
            this.showError('请先选择水印区域')
            return
          }

          const cropData = this.cropper.getData()
          const watermarkType = this.watermarkType.value

          // 验证水印设置
          if (watermarkType === 'text') {
            const text = this.watermarkText.value.trim()
            if (!text) {
              this.showError('请输入水印文字')
              return
            }
          } else if (watermarkType === 'image') {
            if (!this.watermarkImageFile) {
              this.showError('请选择水印图片')
              return
            }
          }

          // 创建水印区域
          this.addWatermarkRegion(cropData, watermarkType)
          this.cancelCrop()
        }

        addWatermarkRegion(cropData, type) {
          this.regionCounter++
          const regionId = `region_${this.regionCounter}`

          // 计算相对位置（相对于视频尺寸的百分比）
          const videoWidth = this.videoPreview.videoWidth
          const videoHeight = this.videoPreview.videoHeight
          const imageWidth = this.cropperImage.naturalWidth
          const imageHeight = this.cropperImage.naturalHeight

          const region = {
            id: regionId,
            type: type,
            x: (cropData.x / imageWidth) * 100,
            y: (cropData.y / imageHeight) * 100,
            width: (cropData.width / imageWidth) * 100,
            height: (cropData.height / imageHeight) * 100,
          }

          // 添加水印特定属性
          if (type === 'text') {
            region.text = this.watermarkText.value
            region.fontSize = parseInt(this.fontSize.value)
            region.fontColor = this.fontColor.value
            region.opacity = parseFloat(this.opacity.value)
          } else if (type === 'image') {
            region.imageFile = this.watermarkImageFile
            region.opacity = parseFloat(this.imageOpacity.value)
          }

          this.watermarkRegions.push(region)
          this.updateWatermarkList()
          this.updateProcessButton()

          this.showStatus(`已添加${type === 'text' ? '文字' : '图片'}水印区域`)
        }

        removeWatermarkRegion(regionId) {
          // 从数组中移除
          this.watermarkRegions = this.watermarkRegions.filter(
            (r) => r.id !== regionId
          )

          // 从DOM中移除
          const regionElement = document.getElementById(regionId)
          if (regionElement) {
            regionElement.remove()
          }

          this.updateWatermarkList()
          this.updateProcessButton()
          this.showStatus('已删除水印区域')
        }

        updateWatermarkList() {
          const listContainer = this.watermarkList

          if (this.watermarkRegions.length === 0) {
            listContainer.innerHTML = `
               <div style="text-align: center; color: var(--text-secondary); padding: 20px;">
                 暂无水印区域<br>
                 <small>点击上方按钮添加水印区域</small>
               </div>
             `
            return
          }

          listContainer.innerHTML = ''
          this.watermarkRegions.forEach((region, index) => {
            const item = document.createElement('div')
            item.className = 'watermark-item'
            item.innerHTML = `
               <div class="watermark-item-header">
                 <span class="watermark-item-title">
                   ${region.type === 'text' ? '📝' : '🖼️'} 
                   ${region.type === 'text' ? region.text : '图片水印'} #${
              index + 1
            }
                 </span>
               </div>
               <div class="watermark-item-info">
                 位置: ${region.x.toFixed(1)}%, ${region.y.toFixed(1)}%<br>
                 大小: ${region.width.toFixed(1)}% × ${region.height.toFixed(
              1
            )}%<br>
                 透明度: ${region.opacity}
               </div>
               <div class="watermark-item-actions">
                 <button class="btn-danger" onclick="watermarkAdder.removeWatermarkRegion('${
                   region.id
                 }')">
                   删除
                 </button>
               </div>
             `
            listContainer.appendChild(item)
          })
        }

        clearAllRegions() {
          if (this.watermarkRegions.length === 0) {
            this.showError('没有水印区域需要清除')
            return
          }

          if (confirm('确定要清除所有水印区域吗？')) {
            this.watermarkRegions = []
            this.updateWatermarkList()
            this.updateProcessButton()
            this.showStatus('已清除所有水印区域')
          }
        }

        updateProcessButton() {
          const hasVideo = !!this.videoFile
          const hasRegions = this.watermarkRegions.length > 0
          this.processBtn.disabled = !(hasVideo && hasRegions)
        }

        cancelCrop() {
          const modal = document.getElementById('watermarkModal')
          modal.style.display = 'none'

          if (this.cropper) {
            this.cropper.destroy()
            this.cropper = null
          }

          // 重置水印设置
          this.watermarkType.value = 'text'
          this.watermarkText.value = '水印文字'
          this.fontSize.value = '24'
          this.fontColor.value = '#ffffff'
          this.opacity.value = '0.8'
          this.opacityValue.textContent = '0.8'
          this.imageOpacity.value = '0.8'
          this.imageOpacityValue.textContent = '0.8'
          this.watermarkImage.value = ''
          this.watermarkImageFile = null
          this.toggleWatermarkSettings()
        }

        async processVideo() {
          if (
            !this.ffmpeg ||
            !this.videoFile ||
            this.watermarkRegions.length === 0
          ) {
            this.showError('请确保已加载视频文件并添加了水印区域')
            return
          }

          if (!this.validateTimeRange()) {
            return
          }

          try {
            this.showProgress(0, '准备处理视频(加载字体文件)...')
            this.processBtn.disabled = true

            // 写入视频文件到 FFmpeg
            const videoData = new Uint8Array(await this.videoFile.arrayBuffer())
            await this.ffmpeg.FS('writeFile', 'input.mp4', videoData)

            // 加载字体文件
            const fontResponse = await fetch('./SourceHanSansCN-Regular.ttf')
            const fontData = new Uint8Array(await fontResponse.arrayBuffer())
            await this.ffmpeg.FS(
              'writeFile',
              'SourceHanSansCN-Regular.ttf',
              fontData
            )

            // 处理图片水印文件
            for (let i = 0; i < this.watermarkRegions.length; i++) {
              const region = this.watermarkRegions[i]
              if (region.type === 'image' && region.imageFile) {
                const imageData = new Uint8Array(
                  await region.imageFile.arrayBuffer()
                )
                await this.ffmpeg.FS(
                  'writeFile',
                  `watermark_${i}.png`,
                  imageData
                )
              }
            }

            this.showProgress(20, '构建 FFmpeg 命令...')

            // 构建 FFmpeg 命令
            const command = await this.buildFFmpegCommand()
            console.log('FFmpeg 命令:', command)

            this.showProgress(30, '开始处理视频...')

            // 执行 FFmpeg 命令
            await this.ffmpeg.run(...command)

            this.showProgress(90, '准备下载...')

            // 读取输出文件
            const outputFormat = this.outputFormat.value
            const outputData = this.ffmpeg.FS(
              'readFile',
              `output.${outputFormat}`
            )

            // 创建视频blob
            const blob = new Blob([outputData.buffer], {
              type: `video/${outputFormat}`,
            })
            const url = URL.createObjectURL(blob)

            this.showProgress(100, '处理完成！')

            // 添加到历史记录
            this.addToHistory({
              videoUrl: url,
              originalFileName: this.videoFile.name,
              outputFormat: outputFormat,
              watermarkCount: this.watermarkRegions.length,
              processTime: new Date().toLocaleString(),
              fileSize:
                (outputData.buffer.byteLength / (1024 * 1024)).toFixed(2) +
                ' MB',
            })

            this.showStatus('视频处理完成，已添加到处理记录')

            // 清理进度显示
            setTimeout(() => {
              this.hideProgress()
            }, 2000)
          } catch (error) {
            console.error('视频处理失败:', error)
            this.showError(`视频处理失败: ${error.message}`)
          } finally {
            this.processBtn.disabled = false
          }
        }

        async buildFFmpegCommand() {
          const startTime = document.getElementById('startTime').value
          const endTime = document.getElementById('endTime').value
          const outputFormat = this.outputFormat.value
          const quality = this.quality.value

          let command = []

          // 添加时间范围到主视频输入
          if (parseFloat(startTime) > 0) {
            command.push('-ss', startTime)
          }
          if (
            parseFloat(endTime) > 0 &&
            parseFloat(endTime) !== this.videoPreview.duration
          ) {
            command.push(
              '-t',
              (parseFloat(endTime) - parseFloat(startTime)).toString()
            )
          }
          command.push('-i', 'input.mp4')

          // 构建复杂滤镜
          let filterComplex = ''
          let overlayInputs = 1
          let hasImageWatermark = false
          let imageWatermarkIndex = 0

          // 先处理所有图片水印的缩放和透明度
          for (let i = 0; i < this.watermarkRegions.length; i++) {
            const region = this.watermarkRegions[i]
            if (region.type === 'image') {
              command.push('-i', `watermark_${i}.png`)
              const videoWidth = this.videoPreview.videoWidth
              const videoHeight = this.videoPreview.videoHeight
              const w = Math.round((region.width / 100) * videoWidth)
              const h = Math.round((region.height / 100) * videoHeight)
              const alpha = region.opacity

              if (filterComplex) filterComplex += ';'
              filterComplex += `[${overlayInputs}:v]scale=${w}:${h},format=rgba,colorchannelmixer=aa=${alpha}[wm${i}]`
              overlayInputs++
              hasImageWatermark = true
            }
          }

          // 开始构建overlay链
          let currentInput = '[0:v]'
          let outputLabel = ''

          for (let i = 0; i < this.watermarkRegions.length; i++) {
            const region = this.watermarkRegions[i]
            const videoWidth = this.videoPreview.videoWidth
            const videoHeight = this.videoPreview.videoHeight

            // 计算实际像素位置
            const x = Math.round((region.x / 100) * videoWidth)
            const y = Math.round((region.y / 100) * videoHeight)

            if (region.type === 'text') {
              // 文字水印
              const fontSize = Math.round(region.fontSize * (videoWidth / 1000))
              const fontColor = region.fontColor.replace('#', '')
              const alpha = Math.round(region.opacity * 255)
                .toString(16)
                .padStart(2, '0')

              if (filterComplex && !filterComplex.endsWith(';'))
                filterComplex += ';'
              filterComplex += `${currentInput}drawtext=text='${region.text}':fontfile=SourceHanSansCN-Regular.ttf:x=${x}:y=${y}:fontsize=${fontSize}:fontcolor=${fontColor}${alpha}:box=1:boxcolor=black@0.3:boxborderw=2`

              if (i < this.watermarkRegions.length - 1) {
                outputLabel = `[tmp${i}]`
                filterComplex += outputLabel
                currentInput = outputLabel
              }
            } else if (region.type === 'image') {
              // 图片水印overlay
              if (filterComplex && !filterComplex.endsWith(';'))
                filterComplex += ';'

              if (i < this.watermarkRegions.length - 1) {
                outputLabel = `[tmp${i}]`
                filterComplex += `${currentInput}[wm${i}]overlay=${x}:${y}${outputLabel}`
                currentInput = outputLabel
              } else {
                filterComplex += `${currentInput}[wm${i}]overlay=${x}:${y}`
              }
            }
          }

          // 添加滤镜复杂参数
          if (
            hasImageWatermark ||
            this.watermarkRegions.some((r) => r.type === 'text')
          ) {
            command.push('-filter_complex', filterComplex)
            // 如果有输出标签，使用它；否则使用默认的视频流
            if (outputLabel) {
              command.push('-map', outputLabel)
            } else {
              command.push('-map', '0:v')
            }
            // 如果原视频有音频流，也要映射音频
            command.push('-map', '0:a?')
          } else {
            // 没有水印的情况
            command.push('-c', 'copy')
          }

          // 添加质量设置
          if (quality === 'high') {
            command.push('-crf', '18')
          } else if (quality === 'medium') {
            command.push('-crf', '23')
          } else {
            command.push('-crf', '28')
          }

          // 添加编码设置
          command.push('-c:v', 'libx264', '-c:a', 'aac', '-preset', 'medium')
          command.push(`output.${outputFormat}`)

          return command
        }

        showProgress(percent, message) {
          this.progressContainer.style.display = 'block'
          this.progressFill.style.width = `${percent}%`
          this.progressText.textContent = message
        }

        hideProgress() {
          this.progressContainer.style.display = 'none'
        }

        showStatus(message) {
          this.hideError()
          this.statusMessage.textContent = message
          this.statusMessage.style.display = 'block'
          setTimeout(() => {
            this.statusMessage.style.display = 'none'
          }, 3000)
        }

        showError(message) {
          this.hideStatus()
          this.errorMessage.textContent = message
          this.errorMessage.style.display = 'block'
        }

        hideStatus() {
          this.statusMessage.style.display = 'none'
        }

        hideError() {
          this.errorMessage.style.display = 'none'
        }

        // 历史记录相关方法
        addToHistory(historyItem) {
          this.processHistory.unshift(historyItem)
          this.updateHistoryDisplay()
          this.operationHistory.style.display = 'block'
        }

        updateHistoryDisplay() {
          if (this.processHistory.length === 0) {
            this.historyList.innerHTML = `
              <div style="text-align: center; color: var(--text-secondary); padding: 40px;">
                暂无处理记录<br>
                <small>处理完成的视频将显示在这里</small>
              </div>
            `
            return
          }

          this.historyList.innerHTML = ''
          this.processHistory.forEach((item, index) => {
            const historyElement = this.createHistoryElement(item, index)
            this.historyList.appendChild(historyElement)
          })
        }

        createHistoryElement(item, index) {
          const element = document.createElement('div')
          element.className = 'history-item'
          element.innerHTML = `
            <div class="history-item-header">
              <div class="history-item-title">🎬 ${item.originalFileName}</div>
              <div class="history-item-time">${item.processTime}</div>
            </div>
            <div class="history-item-info">
              <div>📁 格式: ${item.outputFormat.toUpperCase()}</div>
              <div>💾 大小: ${item.fileSize}</div>
              <div>🏷️ 水印数量: ${item.watermarkCount}个</div>
            </div>
            <div class="history-item-actions">
              <button class="btn-preview" onclick="watermarkAdder.previewVideo(${index})">
                👁️ 预览
              </button>
              <button class="btn-download" onclick="watermarkAdder.downloadVideo(${index})">
                💾 下载
              </button>
              <button class="btn-delete" onclick="watermarkAdder.deleteHistory(${index})">
                🗑️ 删除
              </button>
            </div>
          `
          return element
        }

        previewVideo(index) {
          const item = this.processHistory[index]
          if (!item) return

          this.showVideoPreview(item.videoUrl, item.originalFileName)
        }

        downloadVideo(index) {
          const item = this.processHistory[index]
          if (!item) return

          const a = document.createElement('a')
          a.href = item.videoUrl
          a.download = `watermarked_${item.originalFileName.replace(
            /\.[^/.]+$/,
            ''
          )}.${item.outputFormat}`
          a.click()
          this.showStatus('开始下载视频文件')
        }

        deleteHistory(index) {
          if (confirm('确定要删除这条处理记录吗？')) {
            const item = this.processHistory[index]
            if (item && item.videoUrl) {
              URL.revokeObjectURL(item.videoUrl)
            }
            this.processHistory.splice(index, 1)
            this.updateHistoryDisplay()
            this.showStatus('已删除处理记录')

            if (this.processHistory.length === 0) {
              this.operationHistory.style.display = 'none'
            }
          }
        }

        showVideoPreview(videoUrl, fileName) {
          // 创建预览模态框
          const modal = document.createElement('div')
          modal.className = 'modal'
          modal.style.display = 'flex'
          modal.innerHTML = `
            <div class="modal-content" style="max-width: 80%; max-height: 80%;">
              <div class="modal-header">
                <h3>🎬 视频预览 - ${fileName}</h3>
                <span class="modal-close" onclick="this.parentElement.parentElement.parentElement.remove()">&times;</span>
              </div>
              <div class="modal-body" style="padding: 20px; text-align: center;">
                <video controls style="max-width: 100%; max-height: 60vh; border-radius: 10px;">
                  <source src="${videoUrl}" type="video/mp4">
                  您的浏览器不支持视频播放。
                </video>
              </div>
              <div class="modal-footer">
                <button class="btn-success" onclick="this.parentElement.parentElement.parentElement.remove()">
                  关闭预览
                </button>
              </div>
            </div>
          `

          document.body.appendChild(modal)

          // 点击模态框外部关闭
          modal.addEventListener('click', (e) => {
            if (e.target === modal) {
              modal.remove()
            }
          })
        }
      }

      // 初始化应用
      const watermarkAdder = new WatermarkAdder()
    </script>
  </body>
</html>
